package fuse.LaCollaFS.Api;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import fuse.LaCollaFS.Operacions;
import fuse.LaCollaFS.Paxos;

import LaColla.Api.ApplicationsSideApi;
import LaColla.core.data.Event;
import LaColla.core.data.GroupInfo;
import LaColla.core.util.Debug;

public class ApiImpl implements ApplicationsSideApi {

	private String memberId;

	ArrayList<String> members = new ArrayList();

	private String TreeXML = "";

	private Paxos Consens;

	private Hashtable<Integer, Integer> NumAcceptats = new Hashtable<Integer, Integer>();

	public ApiImpl() throws RemoteException {
		super();

	}

	/**
	 * 
	 */

	public void newConnectedMember(String groupId, String userId,
			String memberId) throws RemoteException {
		p("ApiImpl: newConnectedMember " + groupId + " " + userId + " " + memberId);

		boolean a = false;
		for (Iterator iter = members.iterator(); iter.hasNext();) {
			String element = (String) iter.next();
			a = memberId.equals(element);

		}
		if (!a)
			members.add(memberId);

		//p("a val "+a+"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!tinc n members "+members.size());
		this.memberId = memberId;
	}

	public void memberDisconnected(String groupId, String userId)
			throws RemoteException {
		members.remove(userId);
		p("ApiImpl: memberDisconnected " + groupId + " " + userId);

	}

	public void newEvent(String groupId, LaColla.core.data.app.Event evt)
			throws RemoteException {
		// p("holaaaaaaaaa!!!!!");
		p("ApiImpl: -a-newEvent dels altres  " + evt);

	}

	public void newInfoGroup(String userId, String groupId, String aplicId,
			GroupInfo info) throws RemoteException {
		Debug.sayErr("newInfoGroup", "" + info);
	}

	public void exception(String groupId, String message)
			throws RemoteException {
			p("Exceptions!!!!!");
	}

	public void notifyStopTask(String groupId, String idTask, String result)
			throws RemoteException {
		p("notifyStopTask!!!!!!!!!!!");

	}

	public void notifyTaskState(String groupId, String idTask, String state,
			String result) throws RemoteException {
		p("notifyTaskState!!!!!!!!!!!");
	}

	public boolean AppIsAlive(String appId) throws RemoteException {
		// TODO Auto-generated method stub
		return true;
	}

	public void newInstantMsg(String groupId, String userId,
			String destMemberId, Object message) throws RemoteException {

		p("ApiImpl: Missatge instantani " + groupId + " " + userId + " "
				+ message);
		String missatge = (String) message;

		Element root;
		Document doc;
		int id = -1;
		SAXBuilder builder;

		builder = new SAXBuilder();
		try {
			//p("ApiImpl: xml que tinc... " + missatge);
			doc = builder.build(new StringReader(missatge));
			root = doc.getRootElement();

			List l;
			Element e;

			l = root.getChildren();

			if (l.size() >= 3) {
				e = (Element) l.get(2);
				// p(e.getName());
				id = Integer.valueOf(e.getValue());
			}
			//p("ApiImpl : tipus de missatge rebut...." + root.getName());

			if (root.getName().equals("Accept")) {
				// p("hola"+Consens);
				Consens.Accept(id, missatge);
				// p("adeu");
			} else if (root.getName().equals("Accepted")) {
			//	p("ApiImpl: Acepted!");
				// mirar si tinc quorum....
				int Quorum;
				Integer num;
				Quorum = members.size() / 2 + 1;

				num = NumAcceptats.get(id);
				if (num == null)
					num = 0;
				num++;
				if (num == Quorum)
					Consens.Accepted(id, userId, root);
				// Consens.Rebut(id,userId,root);
			}
			if (root.getName().equals("Fi")) {

				int i;

				i = Integer.valueOf(root.getValue());
			//	p("ApiImpl: He rebut un Fi de " + i);
				Consens.Acabat(i);

			}

		} catch (JDOMException e) {
			p("error de JDOM");
			e.printStackTrace();
		} catch (IOException e) {
			p("error del String Reader...");
			e.printStackTrace();
		} catch (Exception e) {
			p("ApiImpl: error al procesar el missatge instantani......");
			e.printStackTrace();
		}

	}

	public void newEvent(String groupId, Event evt) throws RemoteException {
		p("ApiImpl:event lacolla.core.data.event!!!!!!!!!!!!");

		if (evt.getDesciptiveTypeOfEvent().equals("eventApplication")) {
			p("ApiImpl: event Application rebut!!!!!!!!!!!!!!!!!!!!!");
			TreeXML = evt.getEvent();
		} else
			p("ApiImpl:tipus d'event no controlat!!!!!!!");

		// diferenciar entre events de les metadades i del paxos. Si es un event
		// Paxos haurem de cridar a la clase paxos amb el que digui l'event.

	}

	private void p(Object o) {
		System.out.println("ApiImpl : "+o);

	}

	public String getMemberId() {
		// TODO Auto-generated method stub
		return memberId;
	}

	public ArrayList getMembers() {

		return members;
	}

	public void initialize(Object obj) throws java.rmi.RemoteException {
		p("Initialize!!!!!!!!!!!");
	}

	public String getTree() {
		// TODO Auto-generated method stub
		return TreeXML;
	}

	public void setTree(String arbrexml) {
		TreeXML = arbrexml;

	}

	public void DefConsens(Paxos p) {
		Consens = p;
	}

	public int getNumMembers() {
		// TODO Auto-generated method stub
		return members.size();
	}

}
